package com.mxx.common.data.mybatisplus;

import com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper;
import com.baomidou.mybatisplus.core.conditions.SharedString;
import com.baomidou.mybatisplus.core.conditions.query.Query;
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
import com.baomidou.mybatisplus.core.enums.SqlKeyword;
import com.baomidou.mybatisplus.core.enums.SqlLike;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;

import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;

/**
 * @author: mxx
 * @date: 2021/11/4
 * @time: 14:34
 * @Description: 描述信息
 */
public class BindLambdaQueryWrapper<T> extends AbstractLambdaWrapper<T, BindLambdaQueryWrapper<T>> implements Query<BindLambdaQueryWrapper<T>, T, SFunction<T, ?>> {

    private SharedString sqlSelect;
    private Object dataSource;

    public BindLambdaQueryWrapper(Object dataSource) {
        this((T) null, dataSource);


    }

    public BindLambdaQueryWrapper(T entity, Object dataSource) {
        this.dataSource = dataSource;
        this.sqlSelect = new SharedString();
        super.setEntity(entity);
        super.initNeed();
    }

    public BindLambdaQueryWrapper(Class<T> entityClass, Object dataSource) {
        this.dataSource = dataSource;
        this.sqlSelect = new SharedString();
        super.setEntityClass(entityClass);
        super.initNeed();
    }

    BindLambdaQueryWrapper(T entity, Class<T> entityClass, SharedString sqlSelect, AtomicInteger paramNameSeq, Map<String, Object> paramNameValuePairs, MergeSegments mergeSegments, SharedString lastSql, SharedString sqlComment, SharedString sqlFirst, Object dataSource) {
        this.dataSource = dataSource;
        this.sqlSelect = new SharedString();
        super.setEntity(entity);
        super.setEntityClass(entityClass);
        this.paramNameSeq = paramNameSeq;
        this.paramNameValuePairs = paramNameValuePairs;
        this.expression = mergeSegments;
        this.sqlSelect = sqlSelect;
        this.lastSql = lastSql;
        this.sqlComment = sqlComment;
        this.sqlFirst = sqlFirst;
    }

    @SafeVarargs
    public final BindLambdaQueryWrapper<T> select(SFunction<T, ?>... columns) {
        if (ArrayUtils.isNotEmpty(columns)) {
            this.sqlSelect.setStringValue(this.columnsToString(false, columns));
        }

        return (BindLambdaQueryWrapper) this.typedThis;
    }

    public BindLambdaQueryWrapper<T> select(Class<T> entityClass, Predicate<TableFieldInfo> predicate) {
        if (entityClass == null) {
            entityClass = this.getEntityClass();
        } else {
            this.setEntityClass(entityClass);
        }

        Assert.notNull(entityClass, "entityClass can not be null", new Object[0]);
        this.sqlSelect.setStringValue(TableInfoHelper.getTableInfo(entityClass).chooseSelect(predicate));
        return (BindLambdaQueryWrapper) this.typedThis;
    }

    public String getSqlSelect() {
        return this.sqlSelect.getStringValue();
    }

    protected BindLambdaQueryWrapper<T> instance() {
        return new BindLambdaQueryWrapper(this.getEntity(), this.getEntityClass(), (SharedString) null, this.paramNameSeq, this.paramNameValuePairs, new MergeSegments(), SharedString.emptyString(), SharedString.emptyString(), SharedString.emptyString(), dataSource);
    }

    public void clear() {
        super.clear();
        this.sqlSelect.toNull();
    }


    public BindLambdaQueryWrapper<T> eq(SFunction<T, ?> column) {
        Object val = SFunctionUtil.getFieldValue(dataSource, column);
        return super.eq(column, val);

    }

    public BindLambdaQueryWrapper<T> eq(boolean condition, SFunction<T, ?> column) {
        Object val = SFunctionUtil.getFieldValue(dataSource, column);
        return super.eq(condition, column, val);

    }

    public BindLambdaQueryWrapper<T> like(SFunction<T, ?> column) {
        Object val = SFunctionUtil.getFieldValue(dataSource, column);
        return super.like(column, val);

    }

    public BindLambdaQueryWrapper<T> like(boolean condition, SFunction<T, ?> column) {
        Object val = SFunctionUtil.getFieldValue(dataSource, column);
        return super.like(condition, column, val);

    }

    public BindLambdaQueryWrapper<T> likeLeft(SFunction<T, ?> column) {
        Object val = SFunctionUtil.getFieldValue(dataSource, column);
        return super.likeLeft(column, val);

    }

    public BindLambdaQueryWrapper<T> likeRight(SFunction<T, ?> column) {
        Object val = SFunctionUtil.getFieldValue(dataSource, column);
        return super.likeRight(column, val);

    }

    protected BindLambdaQueryWrapper<T> likeValue(boolean condition, SqlKeyword keyword, SFunction<T, ?> column, SqlLike sqlLike) {
        Object val = SFunctionUtil.getFieldValue(dataSource, column);
        return super.likeValue(condition, keyword, column, val, sqlLike);

    }

    public BindLambdaQueryWrapper<T> likeLeft(boolean condition, SFunction<T, ?> column) {
        Object val = SFunctionUtil.getFieldValue(dataSource, column);
        return super.likeLeft(condition, column, val);

    }

    public BindLambdaQueryWrapper<T> likeRight(boolean condition, SFunction<T, ?> column) {
        Object val = SFunctionUtil.getFieldValue(dataSource, column);
        return super.likeRight(condition, column, val);

    }

    public BindLambdaQueryWrapper<T> notLike(SFunction<T, ?> column) {
        Object val = SFunctionUtil.getFieldValue(dataSource, column);
        return super.notLike(column, val);

    }

    public BindLambdaQueryWrapper<T> notLike(boolean condition, SFunction<T, ?> column) {
        Object val = SFunctionUtil.getFieldValue(dataSource, column);
        return super.notLike(condition, column, val);

    }

    public BindLambdaQueryWrapper<T> gt(SFunction<T, ?> column) {
        Object val = SFunctionUtil.getFieldValue(dataSource, column);
        return super.gt(column, val);

    }

    public BindLambdaQueryWrapper<T> gt(boolean condition, SFunction<T, ?> column) {
        Object val = SFunctionUtil.getFieldValue(dataSource, column);
        return super.gt(condition, column, val);

    }

    public BindLambdaQueryWrapper<T> ge(SFunction<T, ?> column) {
        Object val = SFunctionUtil.getFieldValue(dataSource, column);
        return super.ge(column, val);

    }

    public BindLambdaQueryWrapper<T> ge(boolean condition, SFunction<T, ?> column) {
        Object val = SFunctionUtil.getFieldValue(dataSource, column);
        return super.ge(condition, column, val);

    }

    public BindLambdaQueryWrapper<T> ne(SFunction<T, ?> column) {
        Object val = SFunctionUtil.getFieldValue(dataSource, column);
        return super.ne(column, val);
    }

    public BindLambdaQueryWrapper<T> ne(boolean condition, SFunction<T, ?> column) {
        Object val = SFunctionUtil.getFieldValue(dataSource, column);
        return super.ne(condition, column, val);
    }


}
